/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.babble.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.babble.blog.conversion.BlogCategoryConversionMapper;
import com.babble.blog.entity.BlogCategory;
import com.babble.blog.dto.BlogCategorySaveDTO;
import com.babble.blog.dto.BlogCategoryUpdDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springblade.common.exception.MsgException;
import com.babble.blog.mapper.BlogCategoryMapper;
import com.babble.blog.service.IBlogCategoryService;
import com.babble.blog.vo.BlogCategoryVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.common.cache.CacheNames;
import org.springblade.common.enums.CodeMsg;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.utils.RedisUtil;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 博客分类表 服务实现类
 *
 * @author Blade
 * @since 2021-11-19
 */
@Service
@RequiredArgsConstructor
public class BlogCategoryServiceImpl extends ServiceImpl<BlogCategoryMapper, BlogCategory> implements IBlogCategoryService {
	private final RedisUtil redisUtil;
	private final BlogCategoryConversionMapper blogCategoryConversionMapper;
	@Override
	public IPage<BlogCategoryVO> selectBlogCategoryPage(IPage<BlogCategoryVO> page, BlogCategoryVO blogCategory) {
		return page.setRecords(baseMapper.selectBlogCategoryPage(page, blogCategory));
	}

	@Override
	public List<BlogCategory> selectBlogCategory() {
		Object json = redisUtil.get(CacheNames.BLOG_CATEGORYS);
		if(json==null){
			List<BlogCategory> list = this.list(new QueryWrapper<BlogCategory>().orderByAsc("click_count").orderByAsc("update_time"));
			redisUtil.set(CacheNames.BLOG_CATEGORYS, JSON.toJSON(list));
			return list;
		}
		List<BlogCategory> blogCategorys = JSONArray.parseArray(json.toString(), BlogCategory.class);
		return blogCategorys;
	}
	@Override
	public void clickBlogCategory(String id) throws MsgException {
		List<BlogCategory> tag = getBlogCategoryIsId(id);
		if(tag==null || tag.size()==0){
			throw new MsgException(CodeMsg.BLOG_CATEGORYS_EXISTS_ERROR.getCode(),CodeMsg.BLOG_CATEGORYS_EXISTS_ERROR.getMsg());
		}
		BlogCategory entity = tag.get(0);
		Long userId = SecureUtil.getUser().getUserId();
		Object json = redisUtil.get(CacheNames.BLOG_CATEGORYS_CLICK+userId+":"+id);
		if(json==null){
			entity.setClickCount(entity.getClickCount()+1);
			this.updateById(entity);
			redisUtil.set(CacheNames.BLOG_CATEGORYS_CLICK+userId+":"+id,"0",60, TimeUnit.SECONDS);
			//修改redis中的指定分类点击量
			addClickBlogCategory(entity.getId());
			return;
		}
		throw new MsgException(CodeMsg.BLOG_CATEGORYS_CLICK_EXISTS_ERROR.getCode(),CodeMsg.BLOG_CATEGORYS_CLICK_EXISTS_ERROR.getMsg());
	}
	@Override
	public BlogCategory info(String id) throws MsgException {
		List<BlogCategory> blogCategorys = getBlogCategoryIsId(id);
		if(blogCategorys==null || blogCategorys.size()==0){
			throw new MsgException(CodeMsg.BLOG_CATEGORYS_EXISTS_ERROR.getCode(),CodeMsg.BLOG_CATEGORYS_EXISTS_ERROR.getMsg());
		}
		return blogCategorys.get(0);
	}

	@Override
	public void saveBlogCategory(BlogCategorySaveDTO blogCategorySaveDTO) throws MsgException {
		BlogCategory blogCategoryVO = blogCategoryConversionMapper.blogCategorySaveVOToBlogCategory(blogCategorySaveDTO);
		String categoryName = blogCategoryVO.getCategoryName();
		//根据名字获取博客分类集合
		List<BlogCategory> blogCategories = getBlogCategoryIsName(categoryName);
		if(blogCategories!=null && blogCategories.size()!=0){
			throw new MsgException(CodeMsg.BLOG_CATEGORYS_CREATE_EXISTS_ERROR.getCode(),CodeMsg.BLOG_CATEGORYS_CREATE_EXISTS_ERROR.getMsg());
		}
		//添加数据库和redis
		blogCategoryVO.setCreateTime(LocalDateTime.now());
		blogCategoryVO.setUpdateTime(LocalDateTime.now());
		this.save(blogCategoryVO);
		//刷新redis中的数据
		BlogCategory byId = this.getById(blogCategoryVO.getId());
		addBlogCategory(byId);
	}

	@Override
	public void delBlogCategory(String id) {
		this.removeById(id);
		//redis中删除
		del(id);
	}

	@Override
	public void updBlogCategory(BlogCategoryUpdDTO blogCategoryUpdDTO) throws MsgException {
		info(blogCategoryUpdDTO.getId());
		BlogCategory blogCategory = blogCategoryConversionMapper.blogCategoryUpdVOToBlogCategory(blogCategoryUpdDTO);
		blogCategory.setUpdateTime(LocalDateTime.now());
		this.updateById(blogCategory);
		BlogCategory byId = this.getById(blogCategory.getId());
		updBlogCategory(byId);
	}

	//根据name从redis查找
	private List<BlogCategory> getBlogCategoryIsName(String categoryName) {
		List<BlogCategory> blogCategories = selectBlogCategory().stream().filter(item -> {
			if (categoryName.equals(item.getCategoryName())) {
				return true;
			}
			return false;
		}).collect(Collectors.toList());
		return blogCategories;
	}
	//根据ID从redis查找
	private List<BlogCategory> getBlogCategoryIsId(String id) {
		return selectBlogCategory().stream().filter(item->{
			if(item.getId().equals(id)){
				return true;
			}
			return false;
		}).collect(Collectors.toList());
	}
	//根据分类ID增加redis中指定分类的点击量
	private void addClickBlogCategory(String id){
		List<BlogCategory> blogCategories = selectBlogCategory();
		List<BlogCategory> collect = blogCategories.stream().map(item -> {
			if (item.getId().equals(id)) {
				item.setClickCount(item.getClickCount() + 1);
			}
			return item;
		}).collect(Collectors.toList());
		redisUtil.set(CacheNames.BLOG_CATEGORYS, JSON.toJSON(collect));
	}
	//传入的对象增加redis
	private void addBlogCategory(BlogCategory blogCategory){
		List<BlogCategory> blogCategories = selectBlogCategory();
		blogCategories.add(blogCategory);
		redisUtil.set(CacheNames.BLOG_CATEGORYS, JSON.toJSON(blogCategories));
	}
	//通过ID删除redis中数据
	private void del(String id){
		List<BlogCategory> blogCategories = selectBlogCategory();
		List<BlogCategory> collect = blogCategories.stream().filter(item -> {
			if (item.getId().equals(id)) {
				return false;
			}
			return true;
		}).collect(Collectors.toList());
		redisUtil.set(CacheNames.BLOG_CATEGORYS, JSON.toJSON(collect));
	}
	//修改数据redis
	private void updBlogCategory(BlogCategory blogCategory){
		List<BlogCategory> blogCategories = selectBlogCategory();
		List<BlogCategory> collect = blogCategories.stream().map(item -> {
			if (item.getId().equals(blogCategory.getId())) {
				return blogCategory;
			}
			return item;
		}).collect(Collectors.toList());
		redisUtil.set(CacheNames.BLOG_CATEGORYS, JSON.toJSON(collect));
	}
}
